home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / srefv12i.zip / counter.rxx < prev    next >
Text File  |  1997-04-16  |  17KB  |  587 lines

  1. /* This is a server-side-include  "counter display" for SRE-Filter.
  2.   See COUNTER.DOC for details on installation and use.
  3.  
  4.   Calling syntax:
  5.    1) as a server side include:
  6.          <!-- INTERPRET FILE COUNTER.RXX file=afile opt1=val1 opt2=.. , 0 -->
  7.       where opt1=var1, etc. are additional options
  8.       and where a , 1 signals "read, but do not augment, the counter"
  9.  
  10.    2) or, from a procedure (such as SENDFILE built in procedure)
  11.        ctval=counter.rxx(optlist,noaugment,usedfile,sel,isent,ilen)
  12.  
  13.   3) or as an in-line image
  14.        typically as <IMG src="counter.rxx?file=afile&graphic="YES"&optx="xxx"&sel="MYDOC1.HTM">
  15.      The graphic="YES" is required, the SEL="a_selector" is highly recommended.
  16.  
  17. Note: if a 5th argument is detected, then this is being called as a
  18.       "server side program" (typically, as <Img src="counter.rxx?option_list">
  19.  
  20. */
  21.  
  22. /* ---- BEGIN USER CONFIGURABLE PARAMETERS SECTION ----------  */
  23. /* where to store .cnt files. 0 means "use documents own directory" */
  24. counter_dir=0
  25.  
  26.  
  27. /* 1=create a .cnt file if none exists, 0=do not 
  28.    if the counter file (passed to counter.rxx) does not exist,
  29.    and create_file=0, counter.rxx will exit without doing anything 
  30. */
  31. create_file=1          
  32.  
  33. /* store info on each request. 0=no, 1=yes */
  34. write_users=1
  35.  
  36. /* suppress inrementing if request is from a same client with
  37.    suppress_recent minutes. If 0, or if write_users=0, this is ignored */
  38. suppress_recent=0
  39.  
  40. /* suppress incrementing if request is fron an OWNER */
  41. suppress_owners=1              /*1=yes, 0=no */
  42.  
  43. /* record using the common-log format  */
  44. common_log_format=1   /* 1=use common log format, 0 = use the save_xxx parameters below */
  45.  
  46. /* the following are used only if write_users=1 and common_log_format=0 */
  47. save_ipname=1           /* 1=save ip name, 0=do not save ip name     */
  48. save_username=1         /* 1=save username (if avaialble),0=do not   */
  49. save_time=1             /* 1= save time (10:01:33), 0= do not        */
  50. save_date=1             /* 1=Save date (10 Feb 1996), 0=do not       */
  51. save_docname=1          /* 1=save "request selector",0=do not          */
  52. save_referer=1          /* 1=save "referer", 0=do not                */
  53. save_browser=1          /* 1= save the "user-agent", 0=do not         */
  54. save_bytes = 1          /* 1 = save # of bytes sent & file size (or approximations thereof */
  55. /* note that client's IP address, and "julian" time are always saved */
  56.  
  57. /* END of user-configurable parameters ***********************************/
  58.  
  59. if counter_dir=' ' then counter_dir=0
  60.  
  61. sspcall=0
  62.  
  63. if write_users<>1 then suppress_recent=0
  64. if datatype(suppress_recent)<>'NUM' then suppress_recent=0
  65.  
  66.  
  67. parse upper arg optlist , noaugment,usedfile2,docname2,bsent,bsize
  68. theverb=bsent
  69.  
  70. if upper(theverb)="GET" | upper(theverb)="POST" then do
  71.   sspcall=1
  72.   noaugment=0 ; usedfile2=' '; docname2=' '
  73.   parse arg  ddir, tempfile, reqstrg,optlist,verb ,uri,user, ,
  74.           basedir ,workdir,privset,enmadd,transaction,verbose, ,
  75.          servername,host_nickname,homedir
  76.   docname=uri
  77.   usedfile=translate(ddir,'\','/')
  78. end
  79.  
  80.  
  81. optlist=translate(optlist,' ','+&')
  82.  
  83. if usedfile2<>' ' then usedfile=usedfile2
  84. if docname2<>' ' then docname=docname2
  85.  
  86. if counter_dir=0 then do
  87.    t1=filespec('d',usedfile)
  88.    t2=filespec('p',usedfile)
  89.    counter_dir=t1||t2
  90. end
  91. counter_dir=strip(counter_dir,'t','\')||'\'
  92.  
  93. if sspcall=0 then do
  94.   t3=filespec('n',usedfile)
  95.   foo=lastpos('.',t3)
  96.   if foo=0 then
  97.     cfile=t3
  98.   else
  99.     cfile=delstr(t3,foo)
  100. end
  101. else do
  102.   cfile='DEFAULT'
  103. end
  104.  
  105. cfile=counter_dir||cfile
  106.  
  107. issilent=0 ; nocommas=0; maxval=21740000 ; ndigits=0 ; minval=0
  108. rollover=0 ; doith=0 ; incit=1 ; dographic=0 ; writesel=' ' ; duration=0
  109. do until optlist=""
  110.   parse var optlist anarg optlist
  111.   parse var anarg avar '=' aval ; 
  112.   avar=strip(upper(avar)); aval=strip(strip(aval),,'"')
  113.   select 
  114.      when avar="FILE" then do
  115.           foo=lastpos('.',aval) ;  
  116.           if foo=0 then
  117.              cfile=counter_dir||aval
  118.           else
  119.              cfile=counter_dir||delstr(aval,foo)
  120.      end
  121.      when avar="SILENT" then issilent=1
  122.      when avar="NOCOMMAS" then nocommas=1
  123.      when avar="MAX" then
  124.         if datatype(aval)='NUM' then maxval=aval
  125.      when avar="WIDTH" then 
  126.         if datatype(aval)='NUM' then ndigits=aval
  127.      when avar="MIN" then 
  128.         if datatype(aval)='NUM' then minval=aval
  129.      when avar="ROLLOVER" then rollover=1
  130.      when avar="DURATION" then do
  131.         if datatype(aval)='NUM' then duration=aval
  132.      end
  133.      when avar="ITH" then  doith=1
  134.      when avar="SEL" then writesel=strip(aval)
  135.      when abbrev(avar,"GRAPHIC")=1 then do
  136.         select
  137.           when wordpos(upper(aval),'N NO 0')>0 then dographic=0
  138.           when abbrev(upper(aval),'NORMAL')=1 then dographic=1
  139.           when abbrev(upper(aval),'NOTINV')=1 then dographic=1
  140.           otherwise     dographic=2
  141.         end
  142.      end
  143.      when avar="INCREMENT" then do
  144.         if datatype(aval)="NUM" then incit=aval
  145.      end
  146.      otherwise nop
  147.    end
  148. end
  149.  
  150. if dographic>0 then do
  151.    nocommas=0 ; 
  152.    doith=0 ; 
  153. end
  154.  
  155. if  ndigits>0 then nocommas=1 
  156.  
  157. if pos('.',cfile)=0 then cfile=cfile||'.cnt'
  158.  
  159. /* if create_file=1, then check for existence of cfile, and create
  160. if missing */
  161. if create_file=1 then do
  162.   if stream(cfile,'c','query exists')=' ' then do
  163.      foo=charout(cfile,'0  ',1)
  164.      if foo>0 then do
  165.          if verbose>1 then say " Error creating counter file: " cfile
  166.          return ' '
  167.      end
  168.      foo=stream(cfile,'c','close')
  169.   end
  170. end
  171.  
  172. /* read it in */
  173. crlf = '0d0a'x
  174. ause=sref_open_read(cfile,30,'BOTH')
  175. if ause<0 then  do                /* couldn't get it */
  176.  
  177.   if verbose>1 then say " Error opening counter file: " cfile
  178.   return ' '
  179. end
  180.  
  181. lily=chars(cfile)
  182. ause=strip(charin(cfile,1,lily),'t','1a'x)
  183.  
  184. /* got a file, let's parse it */
  185. filelins.0=0
  186. iz=0
  187. do until ause=""
  188.       parse  var ause eeo (crlf) ause
  189.      iz=iz+1
  190.      filelins.iz=strip(eeo)
  191. end
  192. if iz=0 then do
  193.    iz=1
  194.    filelins.1=0
  195. end
  196. filelins.0=iz
  197. opstat=iz
  198.  
  199.  
  200. /* find count */
  201. ctval=0 
  202. do ip=1 to opstat
  203.   aline0=translate(filelins.ip,' ','00090d0a'x)
  204.   select
  205.      when aline0=' ' then iterate
  206.      when  abbrev(aline0,';') then iterate
  207.      when datatype(aline0)='NUM' then do
  208.           ctval0=aline0
  209.           ctval=ctval0+INCIT
  210.           CTVAL=Max(CTVAL,MINVAL) ;
  211.           IF ROLLOVER=1 & CTVAL>MAXVAL THEN CTVAL=MINVAL
  212.           CTVAL=Min(CTVAL,MAXVAL)
  213.    /*       filelins.ip=ctval */
  214.           ct_line=ip
  215.           leave
  216.      end
  217.      otherwise iterate
  218.    end
  219. end
  220. if ctval=0 then do
  221.      ctval=minval+incit
  222.      ctval0=ctval
  223.      itmp=filelins.0+1
  224. /*     filelins.itmp=ctval */
  225.      filelins.0=itmp
  226.      ct_line=itmp
  227. end
  228.  
  229. numeric digits 12
  230. d1=date('b')
  231. t1=time('m')/(24*60)
  232. nowtime=d1+t1
  233. anaddr=extract('clientaddr')
  234. nowrite=0
  235.  
  236.  
  237. /* no augment? */
  238. if noaugment=1 then do
  239.   nowrite=1 ; write_users=0
  240.   ctval=ctval0
  241. end
  242.  
  243. /* suppress owners? */
  244. if nowrite=0 & suppress_owners=1 then do
  245.    daport=extract('serverport')
  246.    owners=value('SREF_'||daport||'_OWNERS')
  247.    if pos(anaddr,owners)>0 then do
  248.         write_users=0 ; nowrite=1 ;ctval=ctval0 /* no write, don't check */
  249.    end
  250. end
  251.  
  252. /* if suppress_recent, check before incrementing */
  253. if suppress_recent>0 & write_users=1 then do
  254.   chktime=nowtime-(suppress_recent/(24*60))
  255.   do iy=filelins.0 to ct_line+1 by -1
  256.      aline00=filelins.iy
  257.      if aline00=' ' then iterate
  258.      if abbrev(aline00,';') then iterate
  259.      parse var aline00 anip ',' ajulian ',' .
  260.      ajulian=strip(ajulian)
  261.      if datatype(ajulian)<>"NUM" then iterate
  262.      if ajulian < chktime then leave
  263.      if strip(anip)=anaddr then do
  264.          nowrite=1 ; ctval=ctval0; leave
  265.      end
  266.   end
  267. end
  268.  
  269. if incit=0 then nowrite=1   /* increment=0 is a "no augment" signal */
  270.  
  271. filelins.ct_line=ctval          /* record "augmented?" count */
  272.  
  273. /* if "duration" is <> 0, then check entries (this is used to report
  274. "hits in last week" */
  275.  
  276. if duration>0  then do
  277.   if write_users<>1 then do
  278.       ctval="000"
  279.    end
  280.    else do
  281.      ctval=1
  282.      chkdate=trunc(1+nowtime-duration)
  283.      do iy=filelins.0 to ct_line+1 by -1
  284.          aline00=filelins.iy
  285.          if aline00=' ' then iterate
  286.          if abbrev(aline00,';') then iterate
  287.          parse var aline00 anip ',' ajulian ',' poop
  288.          ajulian=trunc(strip(ajulian))
  289.          if datatype(ajulian)<>"NUM" then iterate
  290.          if ajulian < chkdate then leave
  291.          ctval=ctval+1
  292.       end
  293.   end   /* write_users */
  294. end  /* duration>0 */
  295.  
  296. aline=anaddr||', '||nowtime
  297. noss=0
  298.  
  299. /* write out an entry */
  300. IF nowrite=0 & write_users=1  & common_log_format=1 then do
  301.   itmp=filelins.0+1
  302.   if writesel<> ' ' then
  303.       thereq=writesel
  304.   else
  305.      thereq=docname
  306.  
  307. /* fake routine starts here --------------------- */
  308. thereq='/'||strip(thereq,'l','/')
  309.  
  310. mkme=extract('clientmethod')
  311.  
  312.  d1=space(strip(date('n'))); d1=translate(d1,'/',' ')
  313.  t1=time('n')
  314.  d1t1=d1||':'||t1
  315.  
  316.  agmt=gmtoffset()
  317.  if datatype(agmt)='NUM' then do
  318.          agmt=agmt/36
  319.          if abs(agmt)<1000 then do
  320.              if agmt>0 then
  321.                  agmt='0'||agmt
  322.              else
  323.                  agmt='-0'||abs(agmt)
  324.          end
  325.  end
  326.  d1t1=d1t1||' '||agmt
  327.  
  328.   mkme=mkme||' '||thereq
  329.   mkme=mkme||' '||extract('clientprotocol')
  330.   d1t1='['||d1t1||']'
  331.   clientname0=clientname()
  332.   record2='- '||extract('bytessent')
  333.  
  334.   username='-'
  335.   goo=reqfield('AUTHORIZATION:')
  336.   if goo<>' ' then do
  337.           parse var goo . m64 .              /* get the encoded cookie */
  338.           dec=pack64(m64)                       /* and decode it */
  339.           parse upper var dec username ':' pwd      /* split to userid and pwd*/
  340.   end
  341.  
  342.   aline2=clientname0||' - '||username||' '||d1t1||' "'||mkme||'" '||record2
  343.   noss=1
  344. /* fake routine ends here --------------- */
  345.  
  346.  
  347.  
  348.   filelins.itmp=aline||', '||aline2
  349.   filelins.0=itmp
  350. end
  351.  
  352.  itmp=filelins.0+1
  353.  
  354. /* check various conditions: username ipname time date docname referer
  355. */
  356. if noss=0 then do
  357.   if save_username=1 then do
  358.       goo=reqfield('AUTHORIZATION:')
  359.       if goo=' ' then do
  360.           username=' '
  361.       end
  362.       else do
  363.           parse var goo . m64 .              /* get the encoded cookie */
  364.           dec=pack64(m64)                       /* and decode it */
  365.           parse upper var dec username ':' pwd      /* split to userid and pwd*/
  366.       end
  367.       aline=aline||', '||strip(username)
  368.   end
  369.  
  370.   if save_ipname=1 then do
  371.         aline=aline||', '||clientname()
  372.   end
  373.   if save_time=1 then do
  374.          aline=aline||', '||time('n')
  375.   end
  376.   if save_date=1 then do
  377.         aline=aline||', '||date('n')
  378.   end
  379.   if save_docname=1 then do
  380.      if writesel<>' ' then
  381.         aline=aline||', '||writesel
  382.      else
  383.         aline=aline||', '||docname
  384.   end
  385.  
  386.   if save_bytes=1 then do
  387.       if bsent="" then bsent=extract('bytessent')
  388.       if bsize="" then do
  389.          bsize=0
  390.          if  usedfile2 <>  " " then
  391.               bsize=dosdir(usedfile2,'S')
  392.       end
  393.       aline=aline||', '||bsent' 'bsize
  394.   end
  395.  
  396.   if save_referer=1 then do
  397.         aline=aline||', '||reqfield('referer')
  398.   end
  399.   if save_browser=1 then do
  400.         aline=aline||', '||reqfield('user-agent')
  401.   end
  402.   filelins.itmp=aline
  403.   filelins.0=itmp
  404. end
  405.  
  406. /* write out stuff */
  407. if nowrite=0 then do
  408.   stuff=filelins.1
  409.   do mm=2 to filelins.0
  410.      stuff=stuff||crlf||filelins.mm
  411.   end
  412.   stuff=stuff||'             '
  413.   wow=charout(cfile,stuff,1)
  414.   if wow>0 & verbose>0 then say " Warning: problem writing .CNT file: " wow
  415. end
  416. foo=stream(cfile,'c','close')
  417.  
  418. if issilent=1 then return ' '   /* just record, do not display */
  419.  
  420.  
  421. /* format ctval */
  422. ctval=strip(ctval)
  423. ctlen=length(ctval)
  424.  
  425.  
  426. if ndigits>0 then do
  427.     if ctlen<ndigits then do
  428.         ctval=copies('0',ndigits-ctlen)||ctval
  429.     end
  430. end
  431.  
  432.  
  433. if nocommas=0 then do
  434.   il=length(ctval)
  435.   if il>3 then do
  436.       oop=""
  437.       do mm=il to 3 by -3
  438.          tt=substr(ctval,mm-2,3)
  439.          if mm=il then
  440.             oop=tt
  441.          else
  442.             oop=tt||','||oop
  443.       end /* do */
  444.       if mm<>0 then oop=substr(ctval,1,mm)||','||oop
  445.       ctval=oop
  446.   end
  447. end
  448.  
  449.  
  450. if doith=1 then do
  451.   lval2=right(strip(ctval),2)
  452.   if lval2>10 & lval2<20 then
  453.         ctval=ctval||'th'
  454.   else do
  455.      lval=right(strip(ctval),1)
  456.      select
  457.        when lval=0 then  ctval=ctval||'th'
  458.        when lval=1 then ctval=ctval||'st'
  459.        when lval=2 then ctval=ctval||'nd'
  460.        when lval=3 then ctval=ctval||'rd'
  461.        otherwise ctval=ctval||'th'
  462.      end
  463.   end
  464. end
  465.  
  466.  
  467. if dographic=0 then return ctval
  468.  
  469. /**********************************************************/
  470. /* else, return as an xbm file (using d meyer's xcount code) */
  471.  
  472. bytes = '';
  473. bytecount = 0;
  474.  
  475. env = "OS2ENVIRONMENT"
  476. minLen = 7;           /* minimum number of digits in bitmap */
  477. if ndigits>0 then minlen=ndigits
  478. isHigh = 1;           /* if 1, digits are 16 pixels high, to allow room for border */
  479. isInverse = 1;        /* if 1, digits are white on black */
  480. if dographic=1 then isinverse=0
  481.  
  482.    /* bitmap for each digit
  483.       Each digit is 8 pixels wide, 10 high
  484.       invdigits.x are white on black, digits.x black on white */
  485.    invdigits.0 = "c3 99 99 99 99 99 99 99 99 c3";   /* 0 */
  486.    invdigits.1 = "cf c7 cf cf cf cf cf cf cf c7";   /* 1 */
  487.    invdigits.2 = "c3 99 9f 9f cf e7 f3 f9 f9 81";   /* 2 */
  488.    invdigits.3 = "c3 99 9f 9f c7 9f 9f 9f 99 c3";   /* 3 */
  489.    invdigits.4 = "cf cf c7 c7 cb cb cd 81 cf 87";   /* 4 */
  490.    invdigits.5 = "81 f9 f9 f9 c1 9f 9f 9f 99 c3";   /* 5 */
  491.    invdigits.6 = "c7 f3 f9 f9 c1 99 99 99 99 c3";   /* 6 */
  492.    invdigits.7 = "81 99 9f 9f cf cf e7 e7 f3 f3";   /* 7 */
  493.    invdigits.8 = "c3 99 99 99 c3 99 99 99 99 c3";   /* 8 */
  494.    invdigits.9 = "c3 99 99 99 99 83 9f 9f cf e3";   /* 9 */
  495.    
  496.    
  497.       digits.0 = "3c 66 66 66 66 66 66 66 66 3c";   /* 0 */
  498.       digits.1 = "30 38 30 30 30 30 30 30 30 30";   /* 1 */
  499.       digits.2 = "3c 66 60 60 30 18 0c 06 06 7e";   /* 2 */
  500.       digits.3 = "3c 66 60 60 38 60 60 60 66 3c";   /* 3 */
  501.       digits.4 = "30 30 38 38 34 34 32 7e 30 78";   /* 4 */
  502.       digits.5 = "7e 06 06 06 3e 60 60 60 66 3c";   /* 5 */
  503.       digits.6 = "38 0c 06 06 3e 66 66 66 66 3c";   /* 6 */
  504.       digits.7 = "7e 66 60 60 30 30 18 18 0c 0c";   /* 7 */
  505.       digits.8 = "3c 66 66 66 3c 66 66 66 66 3c";   /* 8 */
  506.       digits.9 = "3c 66 66 66 66 7c 60 60 30 1c";   /* 9 */
  507.  
  508. totalreads = ctval
  509. bytecount=0
  510. /* now generate the Bitmap
  511.                     minLen contains minimum number of digits to display
  512.                     isHigh is one for 16 bit high numbers (else 10)
  513.                     isInverse is one for reverse video (white on black) */
  514. /* Stuff 0 to length of counter */
  515. len = Length(totalreads);
  516. crlf = '0a'x        /* image/x-xbitmap format depends on only having a LF char... */
  517. if len < minLen Then len = minlen;
  518.   formattedcount = right(totalreads, len, '0');
  519.  
  520. if isHigh then do 
  521.    do i = 0 to len * 3 - 1 
  522.       if isInverse then
  523.          bytes = bytes"0xff";       /* add three blank rows to each digit */
  524.       else 
  525.          bytes = bytes"0x00";
  526.       bytecount = bytecount + 1;
  527.       if bytecount//len <> 0
  528.       then bytes=bytes','
  529.       else bytes=bytes',' || crlf
  530.    end
  531. end         
  532.       
  533. /* make the digits */
  534. do y = 0 to 9 
  535.    do x = 1 to len
  536.       digit = substr(formattedCount,x,1);
  537.       if isInverse then               /* $inv = 1 for inverted text */
  538.          byte = substr(invdigits.digit, y*3+1,2);
  539.        else 
  540.          byte = substr(digits.digit,y*3+1,2);
  541.          bytes = bytes'0x'byte;
  542.       bytecount = bytecount + 1;
  543.       if bytecount//len <> 0
  544.       then bytes=bytes','
  545.       else bytes=bytes',' || crlf
  546.    end    
  547. end
  548. if isHigh then do
  549.    do i = 0 to len*3 - 1
  550.       if isInverse then
  551.          bytes = bytes"0xff";       /* add three blank rows to each digit */
  552.       else 
  553.          bytes = bytes"0x00";
  554.       bytecount = bytecount + 1;
  555.       if bytecount//len <> 0
  556.       then bytes=bytes','
  557.       else bytes=bytes',' || crlf
  558.    end
  559. end
  560. out_text = "#define count_width "len*8 || crlf
  561. if isHigh then
  562.    out_text = out_text || "#define count_height 16" || crlf
  563. else
  564.    out_text = out_text || "#define count_height 10" || crlf
  565. out_text = out_text || "static char count_bits[] = {" || crlf
  566. out_text = out_text || reverse(substr(reverse(bytes), (2 + length(crlf))))'};' || crlf
  567. 'HEADER NOAUTO'
  568. 'RESPONSE HTTP/1.0 200 OK '     /* Set HTTP response line */
  569. aserv=server()
  570. 'header add Server: ' ||aserv
  571. adate=sref_new_gmt()||'|| GMT '
  572. 'header add Date: '|| adate
  573. 'header add Content-Type: image/x-xbitmap '
  574. llen = Chars(tempfile)            
  575. 'header add Content-Length: '||llen
  576. 'header add Content-Transfer-Encoding: binary '
  577. 'header add Expires: ' ||adate
  578.  
  579. /*wow=dosrename(tempfile,'g:\goserv\temp\me.xbm')*/
  580. 'VAR TYPE image/x-xbitmap name out_text '
  581.  
  582. return 'COUNTER: X-BITMAP sent ' length(out_Text)
  583.  
  584.  
  585.  
  586.  
  587.